package king.dominic.jorc.core;

import android.annotation.SuppressLint;
import android.content.Context;
import android.os.AsyncTask;

import com.googlecode.tesseract.android.TessBaseAPI;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.WeakReference;

import king.dominic.jlibrary.util.FileUtils;


/**
 * Created by DominicKing on 2017/10/26.
 * InitializeORCAsyncTask
 */

class InitializeORCAsyncTask extends AsyncTask<Void, Integer, Boolean> {
    private static final String TAG = "InitializeORCAsyncTask";
    private final TessBaseAPI api;
    private final String mParentDir;
    @SuppressLint("StaticFieldLeak")
    private Context context;
    private OCR.Language language = OCR.Language.ENGLISH;
    private WeakReference<Listener.OnSuccessfulListener> onSuccessfulListenerWeakReference;
    private InputStream inputStream;
    private File outputFile;

    private InitializeORCAsyncTask(Builder builder) {
        api = builder.api;
        language = builder.language;
        context = builder.context;
        onSuccessfulListenerWeakReference = builder.onSuccessfulListener;
        mParentDir = getTessdataParentDir(context);
    }

    @Override
    protected void onPreExecute() {
        inputStream = getAssetsZip(context, language);
        outputFile = new File(getTessdataDir(mParentDir), language.traineddataFileName);
        context = null;
    }

    @Override
    protected Boolean doInBackground(Void... params) {
        File file = outputFile;
        if (file.exists()) {
            init(language);
            return true;
        }
        try {
            boolean success = FileUtils.decompressZip(inputStream, file.getParentFile());
            if (!success) return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
        init(language);
        return true;
    }

    @Override
    protected void onPostExecute(Boolean aBoolean) {
        super.onPostExecute(aBoolean);
        if (onSuccessfulListenerWeakReference != null) {
            Listener.OnSuccessfulListener onSuccessfulListener = onSuccessfulListenerWeakReference.get();
            if (onSuccessfulListener != null) onSuccessfulListener.success(aBoolean);
        }
    }

    private static InputStream getAssetsZip(Context context, OCR.Language language) {
        return FileUtils.getAssetsFileInputStream(context, language.zipFileName);
    }

    private static String getTessdataParentDir(Context context) {
        return context.getFilesDir().getAbsolutePath() + "/orc/";
    }

    private static String getTessdataDir(Context context) {
        return getTessdataDir(getTessdataParentDir(context));
    }

    private static String getTessdataDir(String  parentDir) {
        return parentDir+"tessdata";
    }

    private void init(OCR.Language language) {
//        api.readConfigFile(language.config);
        api.init(mParentDir, language.language);
        api.setVariable("chop_enable", "T");
        api.setVariable("use_new_state_cost", "F");
        api.setVariable("segment_segcost_rating", "F");
        api.setVariable("enable_new_segsearch", "0");
        api.setVariable("language_model_ngram_on", "0");
        api.setVariable("textord_force_make_prop_words", "F");
        api.setVariable("edges_max_children_per_outline", "40");
    }

    public static final class Builder {
        private Context context;
        private final TessBaseAPI api;
        private OCR.Language language;
        private WeakReference<Listener.OnSuccessfulListener> onSuccessfulListener;

        Builder(TessBaseAPI api) {
            this.api = api;
        }

        Builder language(OCR.Language val) {
            language = val;
            return this;
        }

        Builder with(Context val) {
            context = val;
            return this;
        }

        Builder onSuccessfulListener(Listener.OnSuccessfulListener val) {
            onSuccessfulListener = new WeakReference<>(val);
            return this;
        }

        InitializeORCAsyncTask build() {
            return new InitializeORCAsyncTask(this);
        }
    }
}
